package com.qudian.pay.redis;

import java.util.ArrayList;
import java.util.List;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Component;
import com.google.common.primitives.Primitives;
import com.qudian.pay.core.utils.JdkSerializer;
import com.qudian.pay.redis.exception.RedisException;
import com.qudian.pay.redis.support.IRedisList;
import redis.clients.jedis.BinaryClient.LIST_POSITION;
import redis.clients.jedis.ShardedJedis;

/**
 * @Description: Redis List 操作<br>
 */
@Component
public class RedisListManager extends RedisManager implements IRedisList<String> {
	
	@Override
	public List<Object> range(String key, long start, long end) {
		List<Object> list = null;
		ShardedJedis jedis = this.getPool().getResource();
		try {
			List<byte[]> tmpList = jedis.lrange(key.getBytes(charset), start, end);
			if (null != tmpList && !tmpList.isEmpty()) {
				list = new ArrayList<Object>(tmpList.size());
				for (byte[] s : tmpList) {
					if (null != s)
						list.add(JdkSerializer.deSerialize(s));
				}
			}
		} catch (Exception e) {
			throw new RedisException(-1, e.getMessage(), e);
		} finally {
			jedis.close();
		}
		return list;
	}
	
	@Override
	public void trim(String key, long start, long end) {
		ShardedJedis jedis = this.getPool().getResource();
		try {
			jedis.ltrim(key, start, end);
		} catch (Exception e) {
			throw new RedisException(-1, e.getMessage(), e);
		} finally {
			jedis.close();
		}
	}
	
	@Override
	public Long size(String key) {
		ShardedJedis jedis = this.getReadPool().getResource();
		try {
			return jedis.llen(key);
		} catch (Exception e) {
			throw new RedisException(-1, e.getMessage(), e);
		} finally {
			jedis.close();
		}
	}
	
	@Override
	public Long leftPush(String key, Object value) {
		ShardedJedis jedis = this.getPool().getResource();
		try {
			return jedis.lpush((key == null ? null : key.getBytes(charset)),
					null == value ? JdkSerializer.serialize(StringUtils.EMPTY) : JdkSerializer.serialize(value));
		} catch (Exception e) {
			throw new RedisException(-1, e.getMessage(), e);
		} finally {
			jedis.close();
		}
	}
	
	@Override
	public Long leftPushAll(String key, Object... values) {
		ShardedJedis jedis = this.getPool().getResource();
		if (values == null)
			return null;
		try {
			final byte[][] vals = new byte[values.length][];
			int i = 0;
			for (byte[] val : vals) {
				if (null != val)
					vals[i++] = JdkSerializer.serialize(val);
			}
			return jedis.lpush(key.getBytes(charset), vals);
		} catch (Exception e) {
			throw new RedisException(-1, e.getMessage(), e);
		} finally {
			jedis.close();
		}
	}
	
	@Override
	public Long leftPushIfPresent(String key, Object value) {
		ShardedJedis jedis = this.getPool().getResource();
		try {
			return jedis.lpushx((key == null ? null : key.getBytes(charset)),
					null == value ? JdkSerializer.serialize(StringUtils.EMPTY) : JdkSerializer.serialize(value));
		} catch (Exception e) {
			throw new RedisException(-1, e.getMessage(), e);
		} finally {
			jedis.close();
		}
	}
	
	@Override
	public Long leftPush(String key, Object pivot, Object value) {
		ShardedJedis jedis = this.getPool().getResource();
		try {
			return jedis.linsert(key.getBytes(charset), LIST_POSITION.BEFORE,
					null == pivot ? JdkSerializer.serialize(StringUtils.EMPTY) : JdkSerializer.serialize(pivot),
					null == value ? JdkSerializer.serialize(StringUtils.EMPTY) : JdkSerializer.serialize(value));
		} catch (Exception e) {
			throw new RedisException(-1, e.getMessage(), e);
		} finally {
			jedis.close();
		}
	}
	
	@Override
	public Long rightPush(String key, Object value) {
		ShardedJedis jedis = this.getPool().getResource();
		try {
			return jedis.rpush((key == null ? null : key.getBytes(charset)),
					null == value ? JdkSerializer.serialize(StringUtils.EMPTY) : JdkSerializer.serialize(value));
		} catch (Exception e) {
			throw new RedisException(-1, e.getMessage(), e);
		} finally {
			jedis.close();
		}
	}
	
	@Override
	public Long rightPushAll(String key, Object... values) {
		ShardedJedis jedis = this.getPool().getResource();
		if (values == null)
			return null;
		try {
			final byte[][] vals = new byte[values.length][];
			int i = 0;
			for (byte[] val : vals) {
				if (null != val)
					vals[i++] = JdkSerializer.serialize(val);
			}
			return jedis.rpush(key.getBytes(charset), vals);
		} catch (Exception e) {
			throw new RedisException(-1, e.getMessage(), e);
		} finally {
			jedis.close();
		}
	}
	
	@Override
	public Long rightPushIfPresent(String key, Object value) {
		ShardedJedis jedis = this.getPool().getResource();
		try {
			return jedis.rpushx((key == null ? null : key.getBytes(charset)),
					null == value ? JdkSerializer.serialize(StringUtils.EMPTY) : JdkSerializer.serialize(value));
		} catch (Exception e) {
			throw new RedisException(-1, e.getMessage(), e);
		} finally {
			jedis.close();
		}
	}
	
	@Override
	public Long rightPush(String key, Object pivot, Object value) {
		ShardedJedis jedis = this.getPool().getResource();
		try {
			return jedis.linsert(key.getBytes(charset), LIST_POSITION.AFTER,
					null == pivot ? JdkSerializer.serialize(StringUtils.EMPTY) : JdkSerializer.serialize(pivot),
					null == value ? JdkSerializer.serialize(StringUtils.EMPTY) : JdkSerializer.serialize(value));
		} catch (Exception e) {
			throw new RedisException(-1, e.getMessage(), e);
		} finally {
			jedis.close();
		}
	}
	
	@Override
	public void set(String key, long index, Object value) {
		ShardedJedis jedis = this.getPool().getResource();
		try {
			jedis.lset((key == null ? null : key.getBytes(charset)), index,
					null == value ? JdkSerializer.serialize(StringUtils.EMPTY) : JdkSerializer.serialize(value));
		} catch (Exception e) {
			throw new RedisException(-1, e.getMessage(), e);
		} finally {
			jedis.close();
		}
	}
	
	@Override
	public Long remove(String key, long i, Object value) {
		ShardedJedis jedis = this.getPool().getResource();
		try {
			return jedis.lrem((key == null ? null : key.getBytes(charset)), i,
					null == value ? JdkSerializer.serialize(StringUtils.EMPTY) : JdkSerializer.serialize(value));
		} catch (Exception e) {
			throw new RedisException(-1, e.getMessage(), e);
		} finally {
			jedis.close();
		}
	}
	
	@Override
	public <T> T index(String key, long index, Class<T> classOfT) {
		ShardedJedis jedis = this.getReadPool().getResource();
		try {
			return Primitives.wrap(classOfT).cast(JdkSerializer.deSerialize(jedis.lindex(key, index).getBytes()));
		} catch (Exception e) {
			throw new RedisException(-1, e.getMessage(), e);
		} finally {
			jedis.close();
		}
	}
	
	@Override
	public <T> T leftPop(String key, Class<T> classOfT) {
		ShardedJedis jedis = this.getPool().getResource();
		try {
			byte[] bytes = jedis.lpop((key == null ? null : ((String) key).getBytes(charset)));
			if (null == bytes)
				return null;
			return Primitives.wrap(classOfT).cast(JdkSerializer.deSerialize(bytes));
		} catch (Exception e) {
			throw new RedisException(-1, e.getMessage(), e);
		} finally {
			jedis.close();
		}
	}
	
	@Override
	public <T> T rightPop(String key, Class<T> classOfT) {
		ShardedJedis jedis = this.getPool().getResource();
		try {
			byte[] bytes = jedis.rpop((key == null ? null : ((String) key).getBytes(charset)));
			if (null == bytes)
				return null;
			return Primitives.wrap(classOfT).cast(JdkSerializer.deSerialize(bytes));
		} catch (Exception e) {
			throw new RedisException(-1, e.getMessage(), e);
		} finally {
			jedis.close();
		}
	}
}
